package com.ala4.oxcafe.service.impl;

import com.ala4.oxcafe.boot.page.PageDomain;
import com.ala4.oxcafe.boot.utils.DetailsHelper;
import com.ala4.oxcafe.common.utils.collection.CollUtil;
import com.ala4.oxcafe.common.utils.event.SpringEventUtil;
import com.ala4.oxcafe.common.utils.object.ObjectUtil;
import com.ala4.oxcafe.common.utils.text.StrUtil;
import com.ala4.oxcafe.constants.OrderNoConstant;
import com.ala4.oxcafe.dto.ServiceAuditDTO;
import com.ala4.oxcafe.dto.sms.EffectNoticeParam;
import com.ala4.oxcafe.entity.*;
import com.ala4.oxcafe.enums.OperateEnum;
import com.ala4.oxcafe.event.SendSmsEvent;
import com.ala4.oxcafe.exception.BusinessException;
import com.ala4.oxcafe.repository.*;
import com.ala4.oxcafe.service.ServiceOrderService;
import com.ala4.oxcafe.utils.CodeGenUtil;
import com.aliyun.sms.SMSTemplateEnum;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 服务单
 *
 * @author PING
 * @version 1.0.0
 * @date 2025/8/15 12:03
 */
@Slf4j
@Service
@AllArgsConstructor
public class ServiceOrderServiceImpl implements ServiceOrderService {

    private final ServiceOrderRepository serviceOrderRepository;

    private final ServiceOrderDetailRepository serviceOrderDetailRepository;

    private final FilmProductRepository filmProductRepository;

    private final WarrantyOrderRepository warrantyOrderRepository;

    private final WeChatUserRepository weChatUserRepository;

    private final StoreInfoRepository storeInfoRepository;

    @Override
    public IPage<ServiceOrder> serviceOrderPage(PageDomain pageDomain, ServiceOrder serviceOrder) {
        return serviceOrderRepository.selectServiceOrderPage(pageDomain, serviceOrder);
    }

    @Override
    public List<ServiceOrder> serviceOrderList(ServiceOrder serviceOrder) {
        return serviceOrderRepository.selectServiceOrderList(serviceOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceOrder createServiceOrder(ServiceOrder serviceOrder) {
        // 创建服务单
        String serviceNo = CodeGenUtil.getDateFormatHHCode(OrderNoConstant.SERVICE_ORDER);
        serviceOrder.setServiceNo(serviceNo);
        serviceOrder.setStatus(0);

        // 从用户信息获取门店信息
        if (DetailsHelper.getUserDetails().getIsStoreUser() != 0) {
            throw new BusinessException("不是门店用户,无法创建服务单");
        }
        Long storeId = DetailsHelper.getUserDetails().getStoreId();
        StoreInfo storeInfo = storeInfoRepository.getById(storeId);
        serviceOrder.setStoreId(storeInfo.getId());
        serviceOrder.setStoreCode(storeInfo.getStoreCode());
        serviceOrder.setStoreName(storeInfo.getStoreName());

        serviceOrderRepository.save(serviceOrder);

        // 创建服务单明细
        this.createServiceOrderDetail(serviceOrder);

        return serviceOrder;
    }

    /**
     * 创建服务单明细
     *
     * @param serviceOrder
     */
    private void createServiceOrderDetail(ServiceOrder serviceOrder) {

        List<ServiceOrderDetail> serviceOrderDetails = serviceOrder.getServiceOrderDetails();
        if (CollUtil.isEmpty(serviceOrderDetails)) {
            throw new BusinessException("请添加一条施工产品");
        }

        List<Long> productIds = serviceOrderDetails.stream().map(ServiceOrderDetail::getProductId).toList();
        Map<Long, FilmProduct> filmProductMap = filmProductRepository.listToMap(productIds);
        for (ServiceOrderDetail serviceOrderDetail : serviceOrderDetails) {
            FilmProduct filmProduct = filmProductMap.get(serviceOrderDetail.getProductId());
            if (ObjectUtil.isNull(filmProduct)) {
                throw new BusinessException("找不到施工产品[{}]", serviceOrderDetail.getProductName());
            }
            serviceOrderDetail.setId(null);
            serviceOrderDetail.setProductSeries(filmProduct.getSeries());
            serviceOrderDetail.setProductName(filmProduct.getNameCn());
            serviceOrderDetail.setServiceId(serviceOrder.getId());
        }
        serviceOrderDetailRepository.saveBatch(serviceOrderDetails);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceOrder updateServiceOrder(ServiceOrder serviceOrder) {

        ServiceOrder dbServiceOrder = serviceOrderRepository.getById(serviceOrder.getId());
        if (ObjectUtil.isNull(dbServiceOrder)) {
            throw new BusinessException("找不到服务单信息");
        }
        if (dbServiceOrder.getStatus() == 1) {
            throw new BusinessException("服务单已审核,不能重新修改");
        }
        // 编辑后更新待审核
        serviceOrder.setStatus(0);
        // 更新服务单
        serviceOrderRepository.updateById(serviceOrder);

        // 删除明细
        serviceOrderDetailRepository.remove(Wrappers.<ServiceOrderDetail>lambdaQuery().eq(ServiceOrderDetail::getServiceId, serviceOrder.getId()));

        // 重新添加明细
        this.createServiceOrderDetail(serviceOrder);

        return serviceOrder;
    }

    @Override
    public ServiceOrder serviceOrderInfo(Long serviceId) {
        ServiceOrder serviceOrder = serviceOrderRepository.getById(serviceId);
        if (ObjectUtil.isNull(serviceOrder)) {
            throw new BusinessException("找不到服务单信息");
        }

        List<ServiceOrderDetail> list = serviceOrderDetailRepository.list(Wrappers.<ServiceOrderDetail>lambdaQuery().eq(ServiceOrderDetail::getServiceId, serviceId));
        serviceOrder.setServiceOrderDetails(list);
        return serviceOrder;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceOrder audit(ServiceAuditDTO serviceAuditDTO) {

        ServiceOrder serviceOrder = this.serviceOrderInfo(serviceAuditDTO.getId());

        if (serviceOrder.getStatus() != 0) {
            throw new BusinessException("服务单状态不是待审核");
        }

        // 审核通过-按照年限生成质保单
        if (OperateEnum.PASS.equals(serviceAuditDTO.getOperate())) {
            // 状态到以审核
            serviceOrder.setStatus(1);
            if (ObjectUtil.isNull(serviceAuditDTO.getWarrantyPeriod())) {
                throw new BusinessException("请输入质保年限(单位:月)");
            }

            // 生成质保单
            this.createWarrantyOrder(serviceOrder, serviceAuditDTO.getWarrantyPeriod());

            // 生成微信用户
            this.createWeChatUser(serviceOrder);

        } else if (OperateEnum.REJECT.equals(serviceAuditDTO.getOperate())) {
            // 审核驳回 驳回状态到已驳回
            serviceOrder.setStatus(2);
            if (StrUtil.isEmpty(serviceAuditDTO.getAuditOpinions())) {
                throw new BusinessException("驳回审核意见不能为空");
            }
        } else {
            throw new BusinessException("未知的操作");
        }

        serviceOrder.setAuditComments(serviceAuditDTO.getAuditOpinions());
        // 更新服务单
        serviceOrderRepository.updateByIdOptimistic(serviceOrder);

        return serviceOrder;
    }

    /**
     * 服务单创建微信用户
     *
     * @param serviceOrder 服务单
     */
    private void createWeChatUser(ServiceOrder serviceOrder) {
        if (StrUtil.isEmpty(serviceOrder.getCustomerPhone())) {
            throw new BusinessException("服务单手机号不能为空");
        }

        List<WeChatUser> weChatUsers = weChatUserRepository.list(Wrappers.<WeChatUser>lambdaQuery().eq(WeChatUser::getPhoneNumber, serviceOrder.getCustomerPhone()));
        // 如果为空就去创建一个微信用户
        if (CollUtil.isEmpty(weChatUsers)) {
            weChatUserRepository.phoneNameCreateWxUser(serviceOrder.getCustomerPhone(), serviceOrder.getCustomerName(), 0);
        }
    }

    /**
     * 服务单生成质保单
     *
     * @param serviceOrder   服务单
     * @param warrantyPeriod 质保年限
     */
    private void createWarrantyOrder(ServiceOrder serviceOrder, Integer warrantyPeriod) {
        // 创建质保单
        WarrantyOrder warrantyOrder = new WarrantyOrder(serviceOrder);
        warrantyOrder.setWarrantyPeriod(warrantyPeriod);

        // 过保日期 = 施工日期 + 质保年限
        LocalDateTime serviceDate = serviceOrder.getServiceDate();
        warrantyOrder.setExpiredDate(serviceDate.plusMonths(warrantyPeriod).toLocalDate());
        warrantyOrder.setWarrantyNo(CodeGenUtil.getDateFormatHHCode(OrderNoConstant.WARRANTY_ORDER));
        warrantyOrder.setStatus(0);
        warrantyOrder.setOperator(serviceOrder.getOperator());

        warrantyOrderRepository.save(warrantyOrder);

        // 把质保单ID更新的服务单明细上面去
        List<ServiceOrderDetail> serviceOrderDetails = serviceOrder.getServiceOrderDetails();
        if (CollUtil.isEmpty(serviceOrderDetails)) {
            throw new BusinessException("服务单明细不能为空");
        }
        for (ServiceOrderDetail serviceOrderDetail : serviceOrderDetails) {
            serviceOrderDetail.setWarrantyId(warrantyOrder.getId());
        }
        serviceOrderDetailRepository.updateBatchById(serviceOrderDetails);

        // 质保单生成成功发送质保单生效短信
        SpringEventUtil.publishEvent(new SendSmsEvent(SMSTemplateEnum.EFFECT_NOTICE, serviceOrder.getCustomerPhone(), new EffectNoticeParam(warrantyOrder.getWarrantyNo(), warrantyOrder.getExpiredDate())));
    }
}
